#include "include/flow.h"

flow flows[FLOW_MAX_NUM];
int  flow_num;
u64  HP[VM_NUM];

void init_flows() {
    FILE* fp = fopen(FLOW_CSV_PATH, "r");
    if (!fp) {
        perror("无法打开文件");
        return;
    }
    char line[MAX_LINE_SIZE];
    int  cnt = 0;

    // 跳过标题行（id,src,dst,size,relative_dl,period,priority）
    fgets(line, MAX_LINE_SIZE, fp);
    flows[0].priority = -1;
    // 逐行读取数据
    flow_num = 0;
    while (fgets(line, MAX_LINE_SIZE, fp)) {
        flow_num++;
        flows[flow_num].id           = atoi(strtok(line, ","));
        flows[flow_num].src          = atoi(strtok(NULL, ","));
        flows[flow_num].dst          = atoi(strtok(NULL, ","));
        flows[flow_num].critical     = atoi(strtok(NULL, ","));
        flows[flow_num].size         = atoi(strtok(NULL, ","));
        flows[flow_num].period       = atoi(strtok(NULL, ","));
        flows[flow_num].relative_dl  = atoi(strtok(NULL, ","));
        flows[flow_num].cw           = CBIT_WRITE * flows[flow_num].size * 8;
        flows[flow_num].cr           = CBIT_READ * flows[flow_num].size * 8;
        flows[flow_num].priority     = atoi(strtok(NULL, ","));
        flows[flow_num].is_scheduled = false;
        printf(
            "id: %d, src: %d, dst: %d, critical: %d, period: %d, size: %d, relative_dl: %d, cw: "
            "%f, cr: %f\n",
            flow_num, flows[flow_num].src, flows[flow_num].dst, flows[flow_num].critical, flows[flow_num].period,
            flows[flow_num].size, flows[flow_num].relative_dl, flows[flow_num].cw, flows[flow_num].cr);
    }
    fclose(fp);
    INFO("%d flows are initialized\n", flow_num);
    get_HP();
}

int get_flow_src(int flow_id) {
    if (flow_id >= FLOW_MAX_NUM) {
        INFO("flow_id %d is out of range %d\n", flow_id, FLOW_MAX_NUM);
        return -1;
    }
    return flows[flow_id].src;
}

int get_flow_dst(int flow_id) {
    if (flow_id >= FLOW_MAX_NUM) {
        INFO("flow_id %d is out of range %d\n", flow_id, FLOW_MAX_NUM);
        return -1;
    }
    return flows[flow_id].dst;
}

u64 gcd(u64 a, u64 b) {
    while (b != 0) {
        u64 temp = b;
        b        = a % b;
        a        = temp;
    }
    return a;
}

u64 lcm(u64 a, u64 b) {
    return a / gcd(a, b) * b;  // 避免乘法溢出
}

void get_HP() {
    for (int vm = 0; vm < VM_NUM; ++vm) {
        HP[vm] = 1;
        for (size_t i = 1; i <= flow_num; ++i) {
            if (flows[i].src == vm) {
                HP[vm] = lcm(HP[vm], flows[i].period);
            }
            // INFO("HP: %llu, flows[i].period: %llu\n", HP, flows[i].period);
        }
    }
}
